home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / MDB / fbsql.php < prev    next >
PHP Script  |  2004-03-24  |  49KB  |  1,366 lines

  1. <?php
  2. // +----------------------------------------------------------------------+
  3. // | PHP Version 4                                                        |
  4. // +----------------------------------------------------------------------+
  5. // | Copyright (c) 1998-2004 Manuel Lemos, Tomas V.V.Cox,                 |
  6. // | Stig. S. Bakken, Lukas Smith, Frank M. Kromann                       |
  7. // | All rights reserved.                                                 |
  8. // +----------------------------------------------------------------------+
  9. // | MDB is a merge of PEAR DB and Metabases that provides a unified DB   |
  10. // | API as well as database abstraction for PHP applications.            |
  11. // | This LICENSE is in the BSD license style.                            |
  12. // |                                                                      |
  13. // | Redistribution and use in source and binary forms, with or without   |
  14. // | modification, are permitted provided that the following conditions   |
  15. // | are met:                                                             |
  16. // |                                                                      |
  17. // | Redistributions of source code must retain the above copyright       |
  18. // | notice, this list of conditions and the following disclaimer.        |
  19. // |                                                                      |
  20. // | Redistributions in binary form must reproduce the above copyright    |
  21. // | notice, this list of conditions and the following disclaimer in the  |
  22. // | documentation and/or other materials provided with the distribution. |
  23. // |                                                                      |
  24. // | Neither the name of Manuel Lemos, Tomas V.V.Cox, Stig. S. Bakken,    |
  25. // | Lukas Smith nor the names of his contributors may be used to endorse |
  26. // | or promote products derived from this software without specific prior|
  27. // | written permission.                                                  |
  28. // |                                                                      |
  29. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  |
  30. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT    |
  31. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS    |
  32. // | FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE      |
  33. // | REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,          |
  34. // | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
  35. // | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS|
  36. // |  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED  |
  37. // | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT          |
  38. // | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY|
  39. // | WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE          |
  40. // | POSSIBILITY OF SUCH DAMAGE.                                          |
  41. // +----------------------------------------------------------------------+
  42. // | Author: Lukas Smith <smith@dybnet.de>                                |
  43. // +----------------------------------------------------------------------+
  44. //
  45. // $Id: fbsql.php,v 1.16.4.10 2004/01/08 13:43:02 lsmith Exp $
  46. //
  47.  
  48. require_once('MDB/Common.php');
  49.  
  50. /**
  51.  * MDB FrontBase driver
  52.  *
  53.  * Notes:
  54.  * - This driver is fairly untested at this time and shoukd be considered
  55.  *   alpha quality for this reason
  56.  *
  57.  * @package MDB
  58.  * @category Database
  59.  * @author  Lukas Smith <smith@dybnet.de>
  60.  * @author  Frank M. Kromann <frank@kromann.info>
  61.  */
  62. class MDB_fbsql extends MDB_Common
  63. {
  64.     // {{{ properties
  65.  
  66.     var $connection = 0;
  67.     var $connected_host;
  68.     var $connected_user;
  69.     var $connected_password;
  70.     var $connected_port;
  71.     var $opened_persistent = '';
  72.  
  73.     var $escape_quotes = "'";
  74.     var $decimal_factor = 1.0;
  75.     
  76.     var $max_text_length = 32768;
  77.  
  78.     var $highest_fetched_row = array();
  79.     var $columns = array();
  80.  
  81.     // }}}
  82.     // {{{ constructor
  83.  
  84.     /**
  85.     * Constructor
  86.     */
  87.     function MDB_fbsql()
  88.     {
  89.         $this->MDB_Common();
  90.         $this->phptype = 'fbsql';
  91.         $this->dbsyntax = 'fbsql';
  92.         
  93.         $this->supported['Sequences'] = 1;
  94.         $this->supported['Indexes'] = 1;
  95.         $this->supported['AffectedRows'] = 1;
  96.         $this->supported['Summaryfunctions'] = 1;
  97.         $this->supported['OrderByText'] = 1;
  98.         $this->supported['CurrId'] = 1;
  99.         $this->supported['SelectRowRanges'] = 1;
  100.         $this->supported['LOBs'] = 1;
  101.         $this->supported['Replace'] = 1;
  102.         $this->supported['SubSelects'] = 1;
  103.         
  104.         $this->decimal_factor = pow(10.0, $this->decimal_places);
  105.         
  106.         $this->errorcode_map = array(
  107.             1004 => MDB_ERROR_CANNOT_CREATE,
  108.             1005 => MDB_ERROR_CANNOT_CREATE,
  109.             1006 => MDB_ERROR_CANNOT_CREATE,
  110.             1007 => MDB_ERROR_ALREADY_EXISTS,
  111.             1008 => MDB_ERROR_CANNOT_DROP,
  112.             1046 => MDB_ERROR_NODBSELECTED,
  113.             1050 => MDB_ERROR_ALREADY_EXISTS,
  114.             1051 => MDB_ERROR_NOSUCHTABLE,
  115.             1054 => MDB_ERROR_NOSUCHFIELD,
  116.             1062 => MDB_ERROR_ALREADY_EXISTS,
  117.             1064 => MDB_ERROR_SYNTAX,
  118.             1100 => MDB_ERROR_NOT_LOCKED,
  119.             1136 => MDB_ERROR_VALUE_COUNT_ON_ROW,
  120.             1146 => MDB_ERROR_NOSUCHTABLE,
  121.         );
  122.     }
  123.  
  124.     // }}}
  125.     // {{{ errorNative()
  126.  
  127.     /**
  128.      * Get the native error code of the last error (if any) that
  129.      * occured on the current connection.
  130.      *
  131.      * @access public
  132.      *
  133.      * @return int native FrontBase error code
  134.      */
  135.     function errorNative()
  136.     {
  137.         return fbsql_errno($this->connection);
  138.     }
  139.  
  140.     // }}}
  141.     // {{{ fbsqlRaiseError()
  142.  
  143.     /**
  144.      * This method is used to communicate an error and invoke error
  145.      * callbacks etc.  Basically a wrapper for MDB::raiseError
  146.      * that checks for native error msgs.
  147.      *
  148.      * @param integer $errno error code
  149.      * @return object a PEAR error object
  150.      * @access public
  151.      * @see PEAR_Error
  152.      */
  153.     function fbsqlRaiseError($errno = NULL)
  154.     {
  155.         if ($errno == NULL) {
  156.             $errno = $this->errorCode(fbsql_errno($this->connection));
  157.         }
  158.         return($this->raiseError($errno, NULL, NULL, NULL, @fbsql_error($this->connection)));
  159.     }
  160.  
  161.     // }}}
  162.     // {{{ autoCommit()
  163.  
  164.     /**
  165.      * Define whether database changes done on the database be automatically
  166.      * committed. This function may also implicitly start or end a transaction.
  167.      *
  168.      * @param boolean $auto_commit    flag that indicates whether the database
  169.      *                                changes should be committed right after
  170.      *                                executing every query statement. If this
  171.      *                                argument is 0 a transaction implicitly
  172.      *                                started. Otherwise, if a transaction is
  173.      *                                in progress it is ended by committing any
  174.      *                                database changes that were pending.
  175.      *
  176.      * @access public
  177.      *
  178.      * @return mixed MDB_OK on success, a MDB error on failure
  179.      */
  180.     function autoCommit($auto_commit)
  181.     {
  182.         $this->debug('AutoCommit: '.($auto_commit ? 'On' : 'Off'));
  183.         if (!isset($this->supported['Transactions'])) {
  184.             return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  185.                 'Auto-commit transactions: transactions are not in use'));
  186.         }
  187.         if ($this->auto_commit == $auto_commit) {
  188.             return(MDB_OK);
  189.         }
  190.         if ($this->connection) {
  191.             if ($auto_commit) {
  192.                 $result = $this->query('COMMIT');
  193.                 if (MDB::isError($result)) {
  194.                     return($result);
  195.                 }
  196.                 $result = $this->query('SET COMMIT TRUE');
  197.             } else {
  198.                 $result = $this->query('SET COMMIT FALSE');
  199.             }
  200.             if (MDB::isError($result)) {
  201.                 return($result);
  202.             }
  203.         }
  204.         $this->auto_commit = $auto_commit;
  205.         $this->in_transaction = !$auto_commit;
  206.         return(MDB_OK);
  207.     }
  208.  
  209.     // }}}
  210.     // {{{ commit()
  211.  
  212.     /**
  213.      * Commit the database changes done during a transaction that is in
  214.      * progress. This function may only be called when auto-committing is
  215.      * disabled, otherwise it will fail. Therefore, a new transaction is
  216.      * implicitly started after committing the pending changes.
  217.      *
  218.      * @access public
  219.      *
  220.      * @return mixed MDB_OK on success, a MDB error on failure
  221.      */
  222.     function commit()
  223.     {
  224.         $this->debug('Commit Transaction');
  225.         if (!isset($this->supported['Transactions'])) {
  226.             return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  227.                 'Commit transactions: transactions are not in use'));
  228.         }
  229.         if ($this->auto_commit) {
  230.             return($this->raiseError(MDB_ERROR, NULL, NULL,
  231.             'Commit transactions: transaction changes are being auto commited'));
  232.         }
  233.         return($this->query('COMMIT'));
  234.     }
  235.  
  236.     // }}}
  237.     // {{{ rollback()
  238.  
  239.     /**
  240.      * Cancel any database changes done during a transaction that is in
  241.      * progress. This function may only be called when auto-committing is
  242.      * disabled, otherwise it will fail. Therefore, a new transaction is
  243.      * implicitly started after canceling the pending changes.
  244.      *
  245.      * @access public
  246.      *
  247.      * @return mixed MDB_OK on success, a MDB error on failure
  248.      */
  249.     function rollback()
  250.     {
  251.         $this->debug('Rollback Transaction');
  252.         if (!isset($this->supported['Transactions'])) {
  253.             return($this->raiseError(MDB_ERROR_UNSUPPORTED, NULL, NULL,
  254.                 'Rollback transactions: transactions are not in use'));
  255.         }
  256.         if ($this->auto_commit) {
  257.             return($this->raiseError(MDB_ERROR, NULL, NULL,
  258.                 'Rollback transactions: transactions can not be rolled back when changes are auto commited'));
  259.         }
  260.         return($this->query('ROLLBACK'));
  261.     }
  262.  
  263.     // }}}
  264.     // {{{ connect()
  265.  
  266.     /**
  267.      * Connect to the database
  268.      *
  269.      * @return TRUE on success, MDB_Error on failure
  270.      **/
  271.     function connect()
  272.     {
  273.         $port = (isset($this->port) ? $this->port : 0);
  274.         if($this->connection != 0) {
  275.             if (!strcmp($this->connected_host, $this->host)
  276.                 && !strcmp($this->connected_user, $this->user)
  277.                 && !strcmp($this->connected_password, $this->password)
  278.                 && !strcmp($this->connected_port, $port)
  279.                 && $this->opened_persistent == $this->options['persistent'])
  280.             {
  281.                 return(MDB_OK);
  282.             }
  283.             fbsql_close($this->connection);
  284.             $this->connection = 0;
  285.             $this->affected_rows = -1;
  286.         }
  287.         if(!PEAR::loadExtension($this->phptype)) {
  288.             return(PEAR::raiseError(NULL, MDB_ERROR_NOT_FOUND,
  289.                 NULL, NULL, 'extension '.$this->phptype.' is not compiled into PHP',
  290.                 'MDB_Error', TRUE));
  291.         }
  292.  
  293.         $function = ($this->options['persistent'] ? 'fbsql_pconnect' : 'fbsql_connect');
  294.         if(!function_exists($function)) {
  295.             return($this->raiseError(MDB_ERROR_UNSUPPORTED));
  296.         }
  297.  
  298.         @ini_set('track_errors', TRUE);
  299.         $this->connection = @$function(
  300.             $port > 0 ? $port : $this->host,
  301.             $this->user, $this->password);
  302.         @ini_restore('track_errors');
  303.         if ($this->connection <= 0) {
  304.             return($this->raiseError(MDB_ERROR_CONNECT_FAILED, NULL, NULL,
  305.                 $php_errormsg));
  306.         }
  307.  
  308.         if (isset($this->supported['Transactions']) && !$this->auto_commit) {
  309.             if (!fbsql_query('SET AUTOCOMMIT FALSE;', $this->connection)) {
  310.                 fbsql_close($this->connection);
  311.                 $this->connection = 0;
  312.                 $this->affected_rows = -1;
  313.                 return($this->raiseError());
  314.             }
  315.             $this->in_transaction = TRUE;
  316.         }
  317.         $this->connected_host = $this->host;
  318.         $this->connected_user = $this->user;
  319.         $this->connected_password = $this->password;
  320.         $this->connected_port = $port;
  321.         $this->opened_persistent = $this->options['persistent'];
  322.         return(MDB_OK);
  323.     }
  324.  
  325.     // }}}
  326.     // {{{ _close()
  327.     /**
  328.      * all the RDBMS specific things needed close a DB connection
  329.      *
  330.      * @return boolean
  331.      * @access private
  332.      **/
  333.     function _close()
  334.     {
  335.         if ($this->connection != 0) {
  336.             if (isset($this->supported['Transactions']) && !$this->auto_commit) {
  337.                 $result = $this->autoCommit(TRUE);
  338.             }
  339.             fbsql_close($this->connection);
  340.             $this->connection = 0;
  341.             $this->affected_rows = -1;
  342.             if (isset($result) && MDB::isError($result)) {
  343.                 return($result);
  344.             }
  345.  
  346.             unset($GLOBALS['_MDB_databases'][$this->database]);
  347.             return(TRUE);
  348.         }
  349.         return(FALSE);
  350.     }
  351.  
  352.     // }}}
  353.     // {{{ query()
  354.  
  355.     /**
  356.      * Send a query to the database and return any results
  357.      *
  358.      * @access public
  359.      *
  360.      * @param string  $query  the SQL query
  361.      * @param mixed   $types  array that contains the types of the columns in
  362.      *                        the result set
  363.      *
  364.      * @return mixed a result handle or MDB_OK on success, a MDB error on failure
  365.      */
  366.     function query($query, $types = NULL)
  367.     {
  368.         $this->debug("Query: $query");
  369.         $ismanip = MDB::isManip($query);
  370.         $this->last_query = $query;
  371.         $first = $this->first_selected_row;
  372.         $limit = $this->selected_row_limit;
  373.         $this->first_selected_row = $this->selected_row_limit = 0;
  374.  
  375.         $result = $this->connect();
  376.         if (MDB::isError($result)) {
  377.             return($result);
  378.         }
  379.         if($limit > 0) {
  380.             if (!$ismanip) {
  381.                 $query = str_replace('SELECT', "SELECT TOP($first,$limit)", $query);
  382.             }
  383.         }
  384.  
  385.         if ($this->database_name != '') {
  386.             if(!fbsql_select_db($this->database_name, $this->connection)) {
  387.                 return($this->fbsqlRaiseError());
  388.             }
  389.         }
  390.  
  391.         // Add ; to the end of the query. This is required by FrontBase
  392.         $query .= ';';
  393.         if ($result = fbsql_query($query, $this->connection)) {
  394.             if ($ismanip) {
  395.                 $this->affected_rows = fbsql_affected_rows($this->connection);
  396.                 return(MDB_OK);
  397.             } else {
  398.                 $this->highest_fetched_row[$result] = -1;
  399.                 if ($types != NULL) {
  400.                     if (!is_array($types)) {
  401.                         $types = array($types);
  402.                     }
  403.                     if (MDB::isError($err = $this->setResultTypes($result, $types))) {
  404.                         $this->freeResult($result);
  405.                         return($err);
  406.                     }
  407.                 }
  408.                 return($result);
  409.             }
  410.         }
  411.         return($this->fbsqlRaiseError());
  412.     }
  413.  
  414.     // }}}
  415.     // {{{ getColumnNames()
  416.  
  417.     /**
  418.      * Retrieve the names of columns returned by the DBMS in a query result.
  419.      *
  420.      * @param resource   $result    result identifier
  421.      * @return mixed                an associative array variable
  422.      *                              that will hold the names of columns. The
  423.      *                              indexes of the array are the column names
  424.      *                              mapped to lower case and the values are the
  425.      *                              respective numbers of the columns starting
  426.      *                              from 0. Some DBMS may not return any
  427.      *                              columns when the result set does not
  428.      *                              contain any rows.
  429.      *
  430.      *                              a MDB error on failure
  431.      * @access public
  432.      */
  433.     function getColumnNames($result)
  434.     {
  435.         $result_value = intval($result);
  436.         if (!isset($this->highest_fetched_row[$result_value])) {
  437.             return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
  438.                 'Get column names: it was specified an inexisting result set'));
  439.         }
  440.         if (!isset($this->columns[$result_value])) {
  441.             $this->columns[$result_value] = array();
  442.             $columns = fbsql_num_fields($result);
  443.             for($column = 0; $column < $columns; $column++) {
  444.                 $this->columns[$result_value][strtolower(fbsql_field_name($result, $column))] = $column;
  445.             }
  446.         }
  447.         return($this->columns[$result_value]);
  448.     }
  449.  
  450.     // }}}
  451.     // {{{ numCols()
  452.  
  453.     /**
  454.      * Count the number of columns returned by the DBMS in a query result.
  455.      *
  456.      * @param resource    $result        result identifier
  457.      * @access public
  458.      * @return mixed integer value with the number of columns, a MDB error
  459.      *                       on failure
  460.      */
  461.     function numCols($result)
  462.     {
  463.         if (!isset($this->highest_fetched_row[intval($result)])) {
  464.             return($this->raiseError(MDB_ERROR_INVALID, NULL, NULL,
  465.                 'numCols: it was specified an inexisting result set'));
  466.         }
  467.         return(fbsql_num_fields($result));
  468.     }
  469.  
  470.     // }}}
  471.     // {{{ endOfResult()
  472.  
  473.     /**
  474.     * check if the end of the result set has been reached
  475.     *
  476.     * @param resource    $result result identifier
  477.     * @return mixed TRUE or FALSE on sucess, a MDB error on failure
  478.     * @access public
  479.     */
  480.     function endOfResult($result)
  481.     {
  482.         if (!isset($this->highest_fetched_row[$result])) {
  483.             return($this->raiseError(MDB_ERROR, NULL, NULL,
  484.                 'End of result: attempted to check the end of an unknown result'));
  485.         }
  486.         return($this->highest_fetched_row[$result] >= $this->numRows($result)-1);
  487.     }
  488.  
  489.     // }}}
  490.     // {{{ fetch()
  491.  
  492.     /**
  493.     * fetch value from a result set
  494.     *
  495.     * @param resource    $result result identifier
  496.     * @param int    $row    number of the row where the data can be found
  497.     * @param int    $field    field number where the data can be found
  498.     * @return mixed string on success, a MDB error on failure
  499.     * @access public
  500.     */
  501.     function fetch($result, $row, $field)
  502.     {
  503.         $this->highest_fetched_row[$result] = max($this->highest_fetched_row[$result], $row);
  504.         if (is_string($field)) {
  505.             if (intval($field) != $field) {
  506.                 $field = strtoupper($field);
  507.             }
  508.             else
  509.             {
  510.                 $field = intval($field);
  511.             }
  512.         }
  513.         $res = @fbsql_result($result, $row, $field);
  514.         if ($res === FALSE && $res != NULL) {
  515.             return($this->fbsqlRaiseError($errno));
  516.         }
  517.         return($res);
  518.     }
  519.  
  520.     // }}}
  521.     // {{{ fetchClob()
  522.  
  523.     /**
  524.     * fetch a clob value from a result set
  525.     *
  526.     * @param resource    $result result identifier
  527.     * @param int    $row    number of the row where the data can be found
  528.     * @param int    $field    field number where the data can be found
  529.     * @return mixed content of the specified data cell, a MDB error on failure,
  530.     *               a MDB error on failure
  531.     * @access public
  532.     */
  533.     function fetchClob($result, $row, $field)
  534.     {
  535.         return($this->fetchLob($result, $row, $field));
  536.     }
  537.  
  538.     // }}}
  539.     // {{{ fetchBlob()
  540.  
  541.     /**
  542.     * fetch a blob value from a result set
  543.     *
  544.     * @param resource    $result result identifier
  545.     * @param int    $row    number of the row where the data can be found
  546.     * @param int    $field    field number where the data can be found
  547.     * @return mixed content of the specified data cell, a MDB error on failure
  548.     * @access public
  549.     */
  550.     function fetchBlob($result, $row, $field)
  551.     {
  552.         return($this->fetchLob($result, $row, $field));
  553.     }
  554.  
  555.     // }}}
  556.     // {{{ convertResult()
  557.  
  558.     /**
  559.     * convert a value to a RDBMS indepdenant MDB type
  560.     *
  561.     * @param mixed  $value   value to be converted
  562.     * @param int    $type    constant that specifies which type to convert to
  563.     * @return mixed converted value
  564.     * @access public
  565.     */
  566.     function convertResult($value, $type)
  567.     {
  568.         switch($type) {
  569.             case MDB_TYPE_BOOLEAN:
  570.                 return ($value == 'T') ? TRUE : FALSE;
  571.             case MDB_TYPE_DECIMAL:
  572.                 return(sprintf('%.'.$this->decimal_places.'f', doubleval($value)/$this->decimal_factor));
  573.             case MDB_TYPE_FLOAT:
  574.                 return(doubleval($value));
  575.             case MDB_TYPE_TIME:
  576.                 if ($value[0] == '+') {
  577.                     return (substr($value, 1));
  578.                 } else {
  579.                     return($value);
  580.                 }
  581.             default:
  582.                 return($this->_baseConvertResult($value, $type));
  583.         }
  584.     }
  585.  
  586.     // }}}
  587.     // {{{ numRows()
  588.  
  589.     /**
  590.     * returns the number of rows in a result object
  591.     *
  592.      * @param ressource $result a valid result ressouce pointer
  593.     * @return mixed MDB_Error or the number of rows
  594.     * @access public
  595.     */
  596.     function numRows($result)
  597.     {
  598.         return(fbsql_num_rows($result));
  599.     }
  600.  
  601.     // }}}
  602.     // {{{ freeResult()
  603.  
  604.     /**
  605.      * Free the internal resources associated with $result.
  606.      *
  607.      * @param $result result identifier
  608.      * @return boolean TRUE on success, FALSE if $result is invalid
  609.      * @access public
  610.      */
  611.     function freeResult($result)
  612.     {
  613.         if(isset($this->highest_fetched_row[$result])) {
  614.             unset($this->highest_fetched_row[$result]);
  615.         }
  616.         if(isset($this->columns[$result])) {
  617.             unset($this->columns[$result]);
  618.         }
  619.         if(isset($this->result_types[$result])) {
  620.             unset($this->result_types[$result]);
  621.         }
  622.         return(fbsql_free_result($result));
  623.     }
  624.  
  625.     // }}}
  626.     // {{{ getIntegerDeclaration()
  627.  
  628.     /**
  629.      * Obtain DBMS specific SQL code portion needed to declare an integer type
  630.      * field to be used in statements like CREATE TABLE.
  631.      *
  632.      * @param string  $name   name the field to be declared.
  633.      * @param string  $field  associative array with the name of the properties
  634.      *                        of the field being declared as array indexes.
  635.      *                        Currently, the types of supported field
  636.      *                        properties are as follows:
  637.      *
  638.      *                       unsigned
  639.      *                        Boolean flag that indicates whether the field
  640.      *                        should be declared as unsigned integer if
  641.      *                        possible.
  642.      *
  643.      *                       default
  644.      *                        Integer value to be used as default for this
  645.      *                        field.
  646.      *
  647.      *                       notnull
  648.      *                        Boolean flag that indicates whether this field is
  649.      *                        constrained to not be set to NULL.
  650.      * @return string  DBMS specific SQL code portion that should be used to
  651.      *                 declare the specified field.
  652.      * @access public
  653.      */
  654.     function getIntegerDeclaration($name, $field)
  655.     {
  656.         if (isset($field['unsigned'])) {
  657.             $this->warnings[] = "unsigned integer field \"$name\" is being
  658.                 declared as signed integer";
  659.         }
  660.         return("$name INT".(isset($field["default"]) ? " DEFAULT ".$field["default"] : "").(isset($field["notnull"]) ? " NOT NULL" : ""));
  661.     }
  662.  
  663.     // }}}
  664.     // {{{ getTextDeclaration()
  665.  
  666.     /**
  667.      * Obtain DBMS specific SQL code portion needed to declare an text type
  668.      * field to be used in statements like CREATE TABLE.
  669.      *
  670.      * @param string $name name the field to be declared.
  671.      * @param string $field associative array with the name of the properties
  672.      *       of the field being declared as array indexes. Currently, the types
  673.      *       of supported field properties are as follows:
  674.      *
  675.      *       length
  676.      *           Integer value that determines the maximum length of the text
  677.      *           field. If this argument is missing the field should be
  678.      *           declared to have the longest length allowed by the DBMS.
  679.      *
  680.      *       default
  681.      *           Text value to be used as default for this field.
  682.      *
  683.      *       notnull
  684.      *           Boolean flag that indicates whether this field is constrained
  685.      *           to not be set to NULL.
  686.      * @return string DBMS specific SQL code portion that should be used to
  687.      *       declare the specified field.
  688.      * @access public
  689.      */
  690.     function getTextDeclaration($name, $field)
  691.     {
  692.         return((isset($field["length"]) ? "$name VARCHAR (".$field["length"].")" : "$name VARCHAR($this->max_text_length)").(isset($field["default"]) ? " DEFAULT ".$this->GetTextValue($field["default"]) : "").(isset($field["notnull"]) ? " NOT NULL" : ""));
  693.     }
  694.  
  695.     // }}}
  696.     // {{{ getClobDeclaration()
  697.  
  698.     /**
  699.      * Obtain DBMS specific SQL code portion needed to declare an character
  700.      * large object type field to be used in statements like CREATE TABLE.
  701.      *
  702.      * @param string  $name   name the field to be declared.
  703.      * @param string  $field  associative array with the name of the
  704.      *                        properties of the field being declared as array
  705.      *                        indexes. Currently, the types of supported field
  706.      *                        properties are as follows:
  707.      *
  708.      *                       length
  709.      *                        Integer value that determines the maximum length
  710.      *                        of the large object field. If this argument is
  711.      *                        missing the field should be declared to have the
  712.      *                        longest length allowed by the DBMS.
  713.      *
  714.      *                       notnull
  715.      *                        Boolean flag that indicates whether this field
  716.      *                        is constrained to not be set to NULL.
  717.      * @return string  DBMS specific SQL code portion that should be used to
  718.      *                 declare the specified field.
  719.      * @access public
  720.      */
  721.     function getClobDeclaration($name, $field)
  722.     {
  723.         return("$name CLOB".
  724.                  (isset($field['notnull']) ? ' NOT NULL' : ''));
  725.     }
  726.  
  727.     // }}}
  728.     // {{{ getBlobDeclaration()
  729.  
  730.     /**
  731.      * Obtain DBMS specific SQL code portion needed to declare an binary large
  732.      * object type field to be used in statements like CREATE TABLE.
  733.      *
  734.      * @param string  $name   name the field to be declared.
  735.      * @param string  $field  associative array with the name of the properties
  736.      *                        of the field being declared as array indexes.
  737.      *                        Currently, the types of supported field
  738.      *                        properties are as follows:
  739.      *
  740.      *                       length
  741.      *                        Integer value that determines the maximum length
  742.      *                        of the large object field. If this argument is
  743.      *                        missing the field should be declared to have the
  744.      *                        longest length allowed by the DBMS.
  745.      *
  746.      *                       notnull
  747.      *                        Boolean flag that indicates whether this field is
  748.      *                        constrained to not be set to NULL.
  749.      * @return string  DBMS specific SQL code portion that should be used to
  750.      *                 declare the specified field.
  751.      * @access public
  752.      */
  753.     function getBlobDeclaration($name, $field)
  754.     {
  755.         return("$name BLOB".
  756.                 (isset($field['notnull']) ? ' NOT NULL' : ''));
  757.     }
  758.  
  759.     // }}}
  760.     // {{{ getBooleanDeclaration()
  761.  
  762.     /**
  763.      * Obtain DBMS specific SQL code portion needed to declare a boolean type
  764.      * field to be used in statements like CREATE TABLE.
  765.      *
  766.      * @param string $name name the field to be declared.
  767.      * @param string $field associative array with the name of the properties
  768.      *       of the field being declared as array indexes. Currently, the types
  769.      *       of supported field properties are as follows:
  770.      *
  771.      *       default
  772.      *           Boolean value to be used as default for this field.
  773.      *
  774.      *       notnullL
  775.      *           Boolean flag that indicates whether this field is constrained
  776.      *           to not be set to NULL.
  777.      * @return string DBMS specific SQL code portion that should be used to
  778.      *       declare the specified field.
  779.      * @access public
  780.      */
  781.     function getBooleanDeclaration($name, $field)
  782.     {
  783.         return("$name BOOLEAN" . (isset($field['default']) ? ' DEFAULT ' . $this->getBooleanValue($field['default']) : '') . (isset($field['notnull']) ? ' NOT NULL' : ''));
  784.     }
  785.  
  786.     // }}}
  787.     // {{{ getDateDeclaration()
  788.  
  789.     /**
  790.      * Obtain DBMS specific SQL code portion needed to declare an date type
  791.      * field to be used in statements like CREATE TABLE.
  792.      *
  793.      * @param string  $name   name the field to be declared.
  794.      * @param string  $field  associative array with the name of the properties
  795.      *                        of the field being declared as array indexes.
  796.      *                        Currently, the types of supported field properties
  797.      *                        are as follows:
  798.      *
  799.      *                       default
  800.      *                        Date value to be used as default for this field.
  801.      *
  802.      *                       notnull
  803.      *                        Boolean flag that indicates whether this field is
  804.      *                        constrained to not be set to NULL.
  805.      * @return string  DBMS specific SQL code portion that should be used to
  806.      *                 declare the specified field.
  807.      * @access public
  808.      */
  809.     function getDateDeclaration($name, $field)
  810.     {
  811.         return("$name DATE".
  812.                 (isset($field['default']) ? " DEFAULT DATE'".$field['default']."'" : '').
  813.                 (isset($field['notnull']) ? ' NOT NULL' : '')
  814.                );
  815.     }
  816.  
  817.     // }}}
  818.     // {{{ getTimestampDeclaration()
  819.  
  820.     /**
  821.      * Obtain DBMS specific SQL code portion needed to declare an timestamp
  822.      * type field to be used in statements like CREATE TABLE.
  823.      *
  824.      * @param string  $name   name the field to be declared.
  825.      * @param string  $field  associative array with the name of the properties
  826.      *                        of the field being declared as array indexes.
  827.      *                        Currently, the types of supported field
  828.      *                        properties are as follows:
  829.      *
  830.      *                       default
  831.      *                        Time stamp value to be used as default for this
  832.      *                        field.
  833.      *
  834.      *                       notnull
  835.      *                        Boolean flag that indicates whether this field is
  836.      *                        constrained to not be set to NULL.
  837.      * @return string  DBMS specific SQL code portion that should be used to
  838.      *                 declare the specified field.
  839.      * @access public
  840.      */
  841.     function getTimestampDeclaration($name, $field)
  842.     {
  843.         return("$name TIMESTAMP".
  844.                 (isset($field['default']) ? " DEFAULT TIMESTAMP'".$field['default']."'" : '').
  845.                 (isset($field['notnull']) ? ' NOT NULL' : '')
  846.                );
  847.     }
  848.  
  849.     // }}}
  850.     // {{{ getTimeDeclaration()
  851.  
  852.     /**
  853.      * Obtain DBMS specific SQL code portion needed to declare an time type
  854.      * field to be used in statements like CREATE TABLE.
  855.      *
  856.      * @param string  $name   name the field to be declared.
  857.      * @param string  $field  associative array with the name of the properties
  858.      *                        of the field being declared as array indexes.
  859.      *                        Currently, the types of supported field
  860.      *                        properties are as follows:
  861.      *
  862.      *                       default
  863.      *                        Time value to be used as default for this field.
  864.      *
  865.      *                       notnull
  866.      *                        Boolean flag that indicates whether this field is
  867.      *                        constrained to not be set to NULL.
  868.      * @return string  DBMS specific SQL code portion that should be used to
  869.      *                 declare the specified field.
  870.      * @access public
  871.      */
  872.     function getTimeDeclaration($name, $field)
  873.     {
  874.         return("$name TIME".
  875.                 (isset($field['default']) ? " DEFAULT TIME'".$field['default']."'" : '').
  876.                 (isset($field['notnull']) ? ' NOT NULL' : '')
  877.                );
  878.     }
  879.  
  880.     // }}}
  881.     // {{{ getFloatDeclaration()
  882.  
  883.     /**
  884.      * Obtain DBMS specific SQL code portion needed to declare an float type
  885.      * field to be used in statements like CREATE TABLE.
  886.      *
  887.      * @param string  $name   name the field to be declared.
  888.      * @param string  $field  associative array with the name of the properties
  889.      *                        of the field being declared as array indexes.
  890.      *                        Currently, the types of supported field
  891.      *                        properties are as follows:
  892.      *
  893.      *                       default
  894.      *                        Integer value to be used as default for this
  895.      *                        field.
  896.      *
  897.      *                       notnull
  898.      *                        Boolean flag that indicates whether this field is
  899.      *                        constrained to not be set to NULL.
  900.      * @return string  DBMS specific SQL code portion that should be used to
  901.      *                 declare the specified field.
  902.      * @access public
  903.      */
  904.     function getFloatDeclaration($name, $field)
  905.     {
  906.         return("$name FLOAT".
  907.                 (isset($field['default']) ?
  908.                  ' DEFAULT '.$this->getFloatValue($field['default']) : '').
  909.                 (isset($field['notnull']) ? ' NOT NULL' : '')
  910.                );
  911.     }
  912.  
  913.     // }}}
  914.     // {{{ getDecimalDeclaration()
  915.  
  916.     /**
  917.      * Obtain DBMS specific SQL code portion needed to declare an decimal type
  918.      * field to be used in statements like CREATE TABLE.
  919.      *
  920.      * @param string  $name   name the field to be declared.
  921.      * @param string  $field  associative array with the name of the properties
  922.      *                        of the field being declared as array indexes.
  923.      *                        Currently, the types of supported field
  924.      *                        properties are as follows:
  925.      *
  926.      *                       default
  927.      *                        Integer value to be used as default for this
  928.      *                        field.
  929.      *
  930.      *                       notnull
  931.      *                        Boolean flag that indicates whether this field is
  932.      *                        constrained to not be set to NULL.
  933.      * @return string  DBMS specific SQL code portion that should be used to
  934.      *                 declare the specified field.
  935.      * @access public
  936.      */
  937.     function getDecimalDeclaration($name, $field)
  938.     {
  939.         return("$name REAL".
  940.                 (isset($field['default']) ?
  941.                  ' DEFAULT '.$this->getDecimalValue($field['default']) : '').
  942.                  (isset($field['notnull']) ? ' NOT NULL' : '')
  943.                );
  944.     }
  945.  
  946.     // }}}
  947.     // {{{ getClobValue()
  948.  
  949.     /**
  950.      * Convert a text value into a DBMS specific format that is suitable to
  951.      * compose query statements.
  952.      *
  953.      * @param resource  $prepared_query query handle from prepare()
  954.      * @param           $parameter
  955.      * @param           $clob
  956.      * @return string  text string that represents the given argument value in
  957.      *                 a DBMS specific format.
  958.      * @access public
  959.      */
  960.     function getClobValue($prepared_query, $parameter, $clob)
  961.     {
  962.         $value = "'";
  963.         while(!$this->endOfLob($clob)) {
  964.             if (MDB::isError($result = $this->readLob($clob, $data, $this->options['lob_buffer_length']))) {
  965.                 return($result);
  966.             }
  967.             $value .= $this->_quote($data);
  968.         }
  969.         $value .= "'";
  970.         return($value);
  971.     }
  972.  
  973.     // }}}
  974.     // {{{ freeClobValue()
  975.  
  976.     /**
  977.      * free a character large object
  978.      *
  979.      * @param resource  $prepared_query query handle from prepare()
  980.      * @param string    $clob
  981.      * @return MDB_OK
  982.      * @access public
  983.      */
  984.     function freeClobValue($prepared_query, $clob)
  985.     {
  986.         unset($this->lobs[$clob]);
  987.         return(MDB_OK);
  988.     }
  989.  
  990.     // }}}
  991.     // {{{ getBlobValue()
  992.  
  993.     /**
  994.      * Convert a text value into a DBMS specific format that is suitable to
  995.      * compose query statements.
  996.      *
  997.      * @param resource  $prepared_query query handle from prepare()
  998.      * @param           $parameter
  999.      * @param           $blob
  1000.      * @return string  text string that represents the given argument value in
  1001.      *                 a DBMS specific format.
  1002.      * @access public
  1003.      */
  1004.     function getBlobValue($prepared_query, $parameter, $blob)
  1005.     {
  1006.         $value = "'";
  1007.         while(!$this->endOfLob($blob)) {
  1008.             if (MDB::isError($result = $this->readLob($blob, $data, $this->options['lob_buffer_length']))) {
  1009.                 return($result);
  1010.             }
  1011.             $value .= addslashes($data);
  1012.         }
  1013.         $value .= "'";
  1014.         return($value);
  1015.     }
  1016.  
  1017.     // }}}
  1018.     // {{{ freeBlobValue()
  1019.  
  1020.     /**
  1021.      * free a binary large object
  1022.      *
  1023.      * @param resource  $prepared_query query handle from prepare()
  1024.      * @param string    $blob
  1025.      * @return MDB_OK
  1026.      * @access public
  1027.      */
  1028.     function freeBlobValue($prepared_query, $blob)
  1029.     {
  1030.         unset($this->lobs[$blob]);
  1031.         return(MDB_OK);
  1032.     }
  1033.  
  1034.     // }}}
  1035.     // {{{ getBooleanValue()
  1036.  
  1037.     /**
  1038.      * Convert a text value into a DBMS specific format that is suitable to
  1039.      * compose query statements.
  1040.      *
  1041.      * @param string $value text string value that is intended to be converted.
  1042.      * @return string text string that represents the given argument value in
  1043.      *       a DBMS specific format.
  1044.      * @access public
  1045.      */
  1046.     function getBooleanValue($value)
  1047.     {
  1048.         return(($value === NULL) ? 'NULL' : ($value ? "True" : "False"));
  1049.     }
  1050.  
  1051.     // }}}
  1052.     // {{{ getDateValue()
  1053.  
  1054.     /**
  1055.      * Convert a text value into a DBMS specific format that is suitable to
  1056.      * compose query statements.
  1057.      * 
  1058.      * @param string $value text string value that is intended to be converted.
  1059.      * @return string text string that represents the given argument value in
  1060.      *        a DBMS specific format.
  1061.      * @access public 
  1062.      */
  1063.     function getDateValue($value)
  1064.     {
  1065.         return(($value === NULL) ? 'NULL' : "DATE'$value'");
  1066.     }
  1067.  
  1068.     // }}}
  1069.     // {{{ getTimestampValue()
  1070.  
  1071.     /**
  1072.      * Convert a text value into a DBMS specific format that is suitable to
  1073.      * compose query statements.
  1074.      * 
  1075.      * @param string $value text string value that is intended to be converted.
  1076.      * @return string text string that represents the given argument value in
  1077.      *        a DBMS specific format.
  1078.      * @access public 
  1079.      */
  1080.     function getTimestampValue($value)
  1081.     {
  1082.         return(($value === NULL) ? 'NULL' : "TIMESTAMP'$value'");
  1083.     }
  1084.  
  1085.     // }}}
  1086.     // {{{ getTimeValue()
  1087.  
  1088.     /**
  1089.      * Convert a text value into a DBMS specific format that is suitable to
  1090.      *        compose query statements.
  1091.      * 
  1092.      * @param string $value text string value that is intended to be converted.
  1093.      * @return string text string that represents the given argument value in
  1094.      *        a DBMS specific format.
  1095.      * @access public 
  1096.      */
  1097.     function getTimeValue($value)
  1098.     {
  1099.         return(($value === NULL) ? 'NULL' : "TIME'$value'");
  1100.     }
  1101.  
  1102.     // }}}
  1103.     // {{{ getFloatValue()
  1104.  
  1105.     /**
  1106.      * Convert a text value into a DBMS specific format that is suitable to
  1107.      * compose query statements.
  1108.      *
  1109.      * @param string  $value text string value that is intended to be converted.
  1110.      * @return string  text string that represents the given argument value in
  1111.      *                 a DBMS specific format.
  1112.      * @access public
  1113.      */
  1114.     function getFloatValue($value)
  1115.     {
  1116.         return(($value === NULL) ? 'NULL' : (float)$value);
  1117.     }
  1118.  
  1119.     // }}}
  1120.     // {{{ getDecimalValue()
  1121.  
  1122.     /**
  1123.      * Convert a text value into a DBMS specific format that is suitable to
  1124.      * compose query statements.
  1125.      *
  1126.      * @param string  $value text string value that is intended to be converted.
  1127.      * @return string  text string that represents the given argument value in
  1128.      *                 a DBMS specific format.
  1129.      * @access public
  1130.      */
  1131.     function getDecimalValue($value)
  1132.     {
  1133.         return(($value === NULL) ? 'NULL' : strval(round(doubleval($value)*$this->decimal_factor)));
  1134.     }
  1135.  
  1136.     // }}}
  1137.     // {{{ nextId()
  1138.  
  1139.     /**
  1140.      * returns the next free id of a sequence
  1141.      *
  1142.      * @param string  $seq_name name of the sequence
  1143.      * @param boolean $ondemand when true the seqence is
  1144.      *                          automatic created, if it
  1145.      *                          not exists
  1146.      *
  1147.      * @return mixed MDB_Error or id
  1148.      * @access public
  1149.      */
  1150.     function nextId($seq_name, $ondemand = TRUE)
  1151.     {
  1152.         $sequence_name = $this->getSequenceName($seq_name);
  1153.         $this->expectError(MDB_ERROR_NOSUCHTABLE);
  1154.         $result = $this->query("INSERT INTO $sequence_name (dummy) VALUES (1)");
  1155.         $this->popExpect();
  1156.         if ($ondemand && MDB::isError($result) &&
  1157.             $result->getCode() == MDB_ERROR_NOSUCHTABLE)
  1158.         {
  1159.             // Since we are create the sequence on demand
  1160.             // we know the first id = 1 so initialize the
  1161.             // sequence at 2
  1162.             $result = $this->createSequence($seq_name, 2);
  1163.             if (MDB::isError($result)) {
  1164.                 return($this->raiseError(MDB_ERROR, NULL, NULL,
  1165.                     'Next ID: on demand sequence could not be created'));
  1166.             } else {
  1167.                 // First ID of a newly created sequence is 1
  1168.                 return(1);
  1169.             }
  1170.         }
  1171.         $value = intval(fbsql_insert_id());
  1172.         $res = $this->query("DELETE FROM $sequence_name WHERE sequence < $value");
  1173.         if (MDB::isError($res)) {
  1174.             $this->warnings[] = 'Next ID: could not delete previous sequence table values';
  1175.         }
  1176.         return($value);
  1177.     }
  1178.  
  1179.     // }}}
  1180.     // {{{ currId()
  1181.  
  1182.     /**
  1183.      * returns the current id of a sequence
  1184.      *
  1185.      * @param string  $seq_name name of the sequence
  1186.      * @return mixed MDB_Error or id
  1187.      * @access public
  1188.      */
  1189.     function currId($seq_name)
  1190.     {
  1191.         $sequence_name = $this->getSequenceName($seq_name);
  1192.         $result = $this->query("SELECT MAX(sequence) FROM $sequence_name", 'integer');
  1193.         if (MDB::isError($result)) {
  1194.             return($result);
  1195.         }
  1196.  
  1197.         return($this->fetchOne($result));
  1198.     }
  1199.  
  1200.     // }}}
  1201.     // {{{ fetchInto()
  1202.  
  1203.     /**
  1204.      * Fetch a row and return data in an array.
  1205.      *
  1206.      * @param resource $result result identifier
  1207.      * @param int $fetchmode ignored
  1208.      * @param int $rownum the row number to fetch
  1209.      * @return mixed data array or NULL on success, a MDB error on failure
  1210.      * @access public
  1211.      */
  1212.     function fetchInto($result, $fetchmode = MDB_FETCHMODE_DEFAULT, $rownum = NULL)
  1213.     {
  1214.         if ($rownum == NULL) {
  1215.             ++$this->highest_fetched_row[$result];
  1216.         } else {
  1217.             if (!@fbsql_data_seek($result, $rownum)) {
  1218.                 return(NULL);
  1219.             }
  1220.             $this->highest_fetched_row[$result] = max($this->highest_fetched_row[$result], $rownum);
  1221.         }
  1222.         if ($fetchmode == MDB_FETCHMODE_DEFAULT) {
  1223.             $fetchmode = $this->fetchmode;
  1224.         }
  1225.         if ($fetchmode & MDB_FETCHMODE_ASSOC) {
  1226.             $row = @fbsql_fetch_assoc($result);
  1227.             if (is_array($row) && $this->options['optimize'] == 'portability') {
  1228.                 $row = array_change_key_case($row, CASE_LOWER);
  1229.             }
  1230.         } else {
  1231.             $row = @fbsql_fetch_row($result);
  1232.         }
  1233.         if (!$row) {
  1234.             if($this->options['autofree']) {
  1235.                 $this->freeResult($result);
  1236.             }
  1237.             return(NULL);
  1238.         }
  1239.         if (isset($this->result_types[$result])) {
  1240.             $row = $this->convertResultRow($result, $row);
  1241.         }
  1242.         return($row);
  1243.     }
  1244.  
  1245.     // }}}
  1246.     // {{{ nextResult()
  1247.  
  1248.     /**
  1249.      * Move the internal fbsql result pointer to the next available result
  1250.      *
  1251.      * @param a valid result resource
  1252.      * @return true if a result is available otherwise return false
  1253.      * @access public
  1254.      */
  1255.     function nextResult($result)
  1256.     {
  1257.         return(fbsql_next_result($result));
  1258.     }
  1259.  
  1260.     // }}}
  1261.     // {{{ tableInfo()
  1262.  
  1263.     /**
  1264.     * returns meta data about the result set
  1265.     *
  1266.     * @param resource    $result    result identifier
  1267.     * @param mixed $mode depends on implementation
  1268.     * @return array an nested array, or a MDB error
  1269.     * @access public
  1270.     */
  1271.     function tableInfo($result, $mode = NULL) {
  1272.         $count = 0;
  1273.         $id     = 0;
  1274.         $res  = array();
  1275.  
  1276.         /*
  1277.          * depending on $mode, metadata returns the following values:
  1278.          *
  1279.          * - mode is false (default):
  1280.          * $result[]:
  1281.          *   [0]['table']  table name
  1282.          *   [0]['name']   field name
  1283.          *   [0]['type']   field type
  1284.          *   [0]['len']    field length
  1285.          *   [0]['flags']  field flags
  1286.          *
  1287.          * - mode is MDB_TABLEINFO_ORDER
  1288.          * $result[]:
  1289.          *   ['num_fields'] number of metadata records
  1290.          *   [0]['table']  table name
  1291.          *   [0]['name']   field name
  1292.          *   [0]['type']   field type
  1293.          *   [0]['len']    field length
  1294.          *   [0]['flags']  field flags
  1295.          *   ['order'][field name]  index of field named 'field name'
  1296.          *   The last one is used, if you have a field name, but no index.
  1297.          *   Test:  if (isset($result['meta']['myfield'])) { ...
  1298.          *
  1299.          * - mode is MDB_TABLEINFO_ORDERTABLE
  1300.          *    the same as above. but additionally
  1301.          *   ['ordertable'][table name][field name] index of field
  1302.          *      named 'field name'
  1303.          *
  1304.          *      this is, because if you have fields from different
  1305.          *      tables with the same field name * they override each
  1306.          *      other with MDB_TABLEINFO_ORDER
  1307.          *
  1308.          *      you can combine MDB_TABLEINFO_ORDER and
  1309.          *      MDB_TABLEINFO_ORDERTABLE with MDB_TABLEINFO_ORDER |
  1310.          *      MDB_TABLEINFO_ORDERTABLE * or with MDB_TABLEINFO_FULL
  1311.          */
  1312.  
  1313.         // if $result is a string, then we want information about a
  1314.         // table without a resultset
  1315.         if (is_string($result)) {
  1316.             $id = @fbsql_list_fields($this->database_name,
  1317.                 $result, $this->connection);
  1318.             if (empty($id)) {
  1319.                 return($this->fbsqlRaiseError());
  1320.             }
  1321.         } else { // else we want information about a resultset
  1322.             $id = $result;
  1323.             if (empty($id)) {
  1324.                 return($this->fbsqlRaiseError());
  1325.             }
  1326.         }
  1327.  
  1328.         $count = @fbsql_num_fields($id);
  1329.  
  1330.         // made this IF due to performance (one if is faster than $count if's)
  1331.         if (empty($mode)) {
  1332.             for ($i = 0; $i<$count; $i++) {
  1333.                 $res[$i]['table'] = @fbsql_field_table ($id, $i);
  1334.                 $res[$i]['name'] = @fbsql_field_name  ($id, $i);
  1335.                 $res[$i]['type'] = @fbsql_field_type  ($id, $i);
  1336.                 $res[$i]['len']  = @fbsql_field_len   ($id, $i);
  1337.                 $res[$i]['flags'] = @fbsql_field_flags ($id, $i);
  1338.             }
  1339.         } else { // full
  1340.             $res['num_fields'] = $count;
  1341.  
  1342.             for ($i = 0; $i<$count; $i++) {
  1343.                 $res[$i]['table'] = @fbsql_field_table ($id, $i);
  1344.                 $res[$i]['name'] = @fbsql_field_name  ($id, $i);
  1345.                 $res[$i]['type'] = @fbsql_field_type  ($id, $i);
  1346.                 $res[$i]['len']  = @fbsql_field_len   ($id, $i);
  1347.                 $res[$i]['flags'] = @fbsql_field_flags ($id, $i);
  1348.                 if ($mode & MDB_TABLEINFO_ORDER) {
  1349.                     $res['order'][$res[$i]['name']] = $i;
  1350.                 }
  1351.                 if ($mode & MDB_TABLEINFO_ORDERTABLE) {
  1352.                     $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
  1353.                 }
  1354.             }
  1355.         }
  1356.  
  1357.         // free the result only if we were called on a table
  1358.         if (is_string($result)) {
  1359.             @fbsql_free_result($id);
  1360.         }
  1361.         return($res);
  1362.     }
  1363. }
  1364.  
  1365. ?>
  1366.